package repository

import (
	"buding-ai/internal/core"
	"buding-ai/internal/repository/model"
	"context"
	"errors"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"
	"gorm.io/gorm"
	"sync"
	"time"
)

var (
	msgRepos *MessageRepository
	msgOnce  sync.Once
)

type MessageRepository struct {
	db *gorm.DB
}

func GetMessageRepository() *MessageRepository {
	msgOnce.Do(func() {
		msgRepos = &MessageRepository{
			db: core.DB,
		}
	})
	return msgRepos
}

func (r *MessageRepository) NewMessage(chatId int64, sequenceNum int, role string, content string, hidden bool) *model.Message {
	return &model.Message{
		ChatId:      int64(chatId),
		SequenceNum: sequenceNum,
		Role:        role,
		Content:     content,
		Timestamp:   time.Now(),
		Hidden:      hidden,
	}
}

func (r *MessageRepository) Create(chatId int64, sequenceNum int, role string, content string, hidden bool) (*model.Message, error) {
	message := r.NewMessage(chatId, sequenceNum, role, content, hidden)
	return r.CreateMessage(message)
}

// CreateMessage 插入一条新消息到MongoDB
func (r *MessageRepository) CreateMessage(msg *model.Message) (*model.Message, error) {
	if msg.Timestamp.IsZero() {
		msg.Timestamp = time.Now()
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	result, err := core.MsgCollection.InsertOne(ctx, msg)
	if err != nil {
		return nil, err
	}

	// 获取插入的ID
	if oid, ok := result.InsertedID.(primitive.ObjectID); ok {
		msg.Id = oid
	}

	return msg, nil
}

// GetMessagesByChatId 根据对话ID获取消息列表
func (r *MessageRepository) GetMessagesByChatId(chatId uint, limit int, skip int, includeHidden bool) ([]*model.Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 将uint类型转换为int64
	chatIdInt64 := int64(chatId)

	// 构建查询条件
	filter := bson.M{"conversation_id": chatIdInt64}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	// 设置分页和排序
	findOptions := options.Find()
	findOptions.SetSort(bson.M{"sequence_num": 1}) // 按序号升序排列

	if limit > 0 {
		findOptions.SetLimit(int64(limit))
	}
	if skip > 0 {
		findOptions.SetSkip(int64(skip))
	}

	// 执行查询
	cursor, err := core.MsgCollection.Find(ctx, filter, findOptions)
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析结果
	var messages []*model.Message
	if err := cursor.All(ctx, &messages); err != nil {
		return nil, err
	}

	return messages, nil
}

// GetAllMessagesByChatId 获取对话的所有消息
func (r *MessageRepository) GetAllMessagesByChatId(chatId uint, includeHidden bool) ([]*model.Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// 将uint类型转换为int64
	chatIdInt64 := int64(chatId)

	// 构建查询条件
	filter := bson.M{"conversation_id": chatIdInt64}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	// 设置排序 - 按序号升序排列
	findOptions := options.Find()
	findOptions.SetSort(bson.M{"sequence_num": 1})

	// 执行查询
	cursor, err := core.MsgCollection.Find(ctx, filter, findOptions)
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析所有结果
	var messages []*model.Message
	if err := cursor.All(ctx, &messages); err != nil {
		return nil, err
	}

	return messages, nil
}

// GetAllMessagesByChatIdInt64 根据int64类型的对话ID获取所有消息
func (r *MessageRepository) GetAllMessagesByChatIdInt64(chatId int64, includeHidden bool) ([]*model.Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// 构建查询条件
	filter := bson.M{"conversation_id": chatId}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	// 设置排序 - 按序号升序排列
	findOptions := options.Find()
	findOptions.SetSort(bson.M{"sequence_num": 1})

	// 执行查询
	cursor, err := core.MsgCollection.Find(ctx, filter, findOptions)
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析所有结果
	var messages []*model.Message
	if err := cursor.All(ctx, &messages); err != nil {
		return nil, err
	}

	return messages, nil
}

// GetMessageById 根据消息ID获取单条消息
func (r *MessageRepository) GetMessageById(id string) (*model.Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 将字符串ID转换为ObjectID
	objectId, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return nil, errors.New("无效的消息ID格式")
	}

	// 构建查询
	filter := bson.M{"_id": objectId}

	// 执行查询
	var message model.Message
	err = core.MsgCollection.FindOne(ctx, filter).Decode(&message)
	if err != nil {
		return nil, err
	}

	return &message, nil
}

// UpdateMessage 更新消息内容
func (r *MessageRepository) UpdateMessage(id string, updates map[string]interface{}) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 将字符串ID转换为ObjectID
	objectId, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return errors.New("无效的消息ID格式")
	}

	// 构建更新操作
	filter := bson.M{"_id": objectId}
	update := bson.M{"$set": updates}

	// 执行更新
	_, err = core.MsgCollection.UpdateOne(ctx, filter, update)
	return err
}

// DeleteMessage 删除消息
func (r *MessageRepository) DeleteMessage(id string) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 将字符串ID转换为ObjectID
	objectId, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return errors.New("无效的消息ID格式")
	}

	// 执行删除
	filter := bson.M{"_id": objectId}
	_, err = core.MsgCollection.DeleteOne(ctx, filter)
	return err
}

// GetLatestMessages 获取最新的N条消息
func (r *MessageRepository) GetLatestMessages(chatId uint, limit int, includeHidden bool) ([]*model.Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 将uint类型转换为int64
	chatIdInt64 := int64(chatId)

	filter := bson.M{"conversation_id": chatIdInt64}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	// 按时间戳降序排序并限制数量
	findOptions := options.Find()
	findOptions.SetSort(bson.M{"timestamp": -1})
	findOptions.SetLimit(int64(limit))

	cursor, err := core.MsgCollection.Find(ctx, filter, findOptions)
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)

	var messages []*model.Message
	if err := cursor.All(ctx, &messages); err != nil {
		return nil, err
	}

	return messages, nil
}

// GetLatestMessagesInt64 获取最新的N条消息(int64版本)
func (r *MessageRepository) GetLatestMessagesInt64(chatId int64, limit int, includeHidden bool) ([]*model.Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	filter := bson.M{"conversation_id": chatId}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	// 按时间戳降序排序并限制数量
	findOptions := options.Find()
	findOptions.SetSort(bson.M{"timestamp": -1})
	findOptions.SetLimit(int64(limit))

	cursor, err := core.MsgCollection.Find(ctx, filter, findOptions)
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)

	var messages []*model.Message
	if err := cursor.All(ctx, &messages); err != nil {
		return nil, err
	}

	return messages, nil
}

// GetMessageCount 获取对话的消息总数
func (r *MessageRepository) GetMessageCount(chatId uint, includeHidden bool) (int64, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 将uint类型转换为int64
	chatIdInt64 := int64(chatId)

	filter := bson.M{"conversation_id": chatIdInt64}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	count, err := core.MsgCollection.CountDocuments(ctx, filter)
	if err != nil {
		return 0, err
	}

	return count, nil
}

// GetMessageCountInt64 获取对话的消息总数(int64版本)
func (r *MessageRepository) GetMessageCountInt64(chatId int64, includeHidden bool) (int64, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	filter := bson.M{"conversation_id": chatId}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	count, err := core.MsgCollection.CountDocuments(ctx, filter)
	if err != nil {
		return 0, err
	}

	return count, nil
}

// BatchCreateMessages 批量插入多条消息
func (r *MessageRepository) BatchCreateMessages(messages []*model.Message) error {
	if len(messages) == 0 {
		return nil
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// 设置当前时间
	now := time.Now()

	// 准备接口数组
	var docs []interface{}
	for _, msg := range messages {
		if msg.Timestamp.IsZero() {
			msg.Timestamp = now
		}
		docs = append(docs, msg)
	}

	// 执行批量插入
	_, err := core.MsgCollection.InsertMany(ctx, docs)
	return err
}

// GetMessagesByFilter 根据自定义过滤条件获取消息
func (r *MessageRepository) GetMessagesByFilter(filter bson.M, limit int, skip int, sort bson.M) ([]*model.Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 设置查询选项
	findOptions := options.Find()

	if sort != nil {
		findOptions.SetSort(sort)
	} else {
		// 默认按时间升序
		findOptions.SetSort(bson.M{"timestamp": 1})
	}

	if limit > 0 {
		findOptions.SetLimit(int64(limit))
	}
	if skip > 0 {
		findOptions.SetSkip(int64(skip))
	}

	// 执行查询
	cursor, err := core.MsgCollection.Find(ctx, filter, findOptions)
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析结果
	var messages []*model.Message
	if err := cursor.All(ctx, &messages); err != nil {
		return nil, err
	}

	return messages, nil
}

// GetMessagesByTimeRange 根据时间范围获取消息(int64版本)
func (r *MessageRepository) GetMessagesByTimeRange(chatId int64, startTime, endTime time.Time, limit int, includeHidden bool) ([]*model.Message, error) {
	// 构建时间范围过滤条件
	filter := bson.M{
		"conversation_id": chatId,
		"timestamp": bson.M{
			"$gte": startTime,
			"$lte": endTime,
		},
	}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	// 按时间升序排序
	sort := bson.M{"timestamp": 1}

	return r.GetMessagesByFilter(filter, limit, 0, sort)
}

// GetMessagesByTimeRangeUint 根据时间范围获取消息(uint版本)
func (r *MessageRepository) GetMessagesByTimeRangeUint(chatId uint, startTime, endTime time.Time, limit int, includeHidden bool) ([]*model.Message, error) {
	// 将uint类型转换为int64
	chatIdInt64 := int64(chatId)

	// 构建时间范围过滤条件
	filter := bson.M{
		"conversation_id": chatIdInt64,
		"timestamp": bson.M{
			"$gte": startTime,
			"$lte": endTime,
		},
	}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	// 按时间升序排序
	sort := bson.M{"timestamp": 1}

	return r.GetMessagesByFilter(filter, limit, 0, sort)
}

// MarkMessagesAsRead 将消息标记为已读（通过元数据）(int64版本)
func (r *MessageRepository) MarkMessagesAsRead(chatId int64, upToSequenceNum int, includeHidden bool) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	filter := bson.M{
		"conversation_id": chatId,
		"sequence_num":    bson.M{"$lte": upToSequenceNum},
		"$or": []bson.M{
			{"metadata.read": bson.M{"$exists": false}},
			{"metadata.read": false},
		},
	}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	update := bson.M{
		"$set": bson.M{
			"metadata.read":      true,
			"metadata.read_time": time.Now(),
		},
	}

	_, err := core.MsgCollection.UpdateMany(ctx, filter, update)
	return err
}

// MarkMessagesAsReadUint 将消息标记为已读（通过元数据）(uint版本)
func (r *MessageRepository) MarkMessagesAsReadUint(chatId uint, upToSequenceNum int, includeHidden bool) error {
	// 将uint类型转换为int64
	chatIdInt64 := int64(chatId)

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	filter := bson.M{
		"conversation_id": chatIdInt64,
		"sequence_num":    bson.M{"$lte": upToSequenceNum},
		"$or": []bson.M{
			{"metadata.read": bson.M{"$exists": false}},
			{"metadata.read": false},
		},
	}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	update := bson.M{
		"$set": bson.M{
			"metadata.read":      true,
			"metadata.read_time": time.Now(),
		},
	}

	_, err := core.MsgCollection.UpdateMany(ctx, filter, update)
	return err
}

// GetMessagesByChatIdInt64 根据int64类型的对话ID获取消息列表
func (r *MessageRepository) GetMessagesByChatIdInt64(chatId int64, limit int, skip int, includeHidden bool) ([]*model.Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 构建查询条件
	filter := bson.M{"conversation_id": chatId}

	// 如果不包含隐藏消息，添加条件
	if !includeHidden {
		filter["$or"] = []bson.M{
			{"hidden": false},
			{"hidden": bson.M{"$exists": false}},
		}
	}

	// 设置分页和排序
	findOptions := options.Find()
	findOptions.SetSort(bson.M{"sequence_num": 1}) // 按序号升序排列

	if limit > 0 {
		findOptions.SetLimit(int64(limit))
	}
	if skip > 0 {
		findOptions.SetSkip(int64(skip))
	}

	// 执行查询
	cursor, err := core.MsgCollection.Find(ctx, filter, findOptions)
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析结果
	var messages []*model.Message
	if err := cursor.All(ctx, &messages); err != nil {
		return nil, err
	}

	return messages, nil
}

// SetMessageHidden 设置消息是否隐藏
func (r *MessageRepository) SetMessageHidden(id string, hidden bool) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 将字符串ID转换为ObjectID
	objectId, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return errors.New("无效的消息ID格式")
	}

	// 构建更新操作
	filter := bson.M{"_id": objectId}
	update := bson.M{"$set": bson.M{"hidden": hidden}}

	// 执行更新
	_, err = core.MsgCollection.UpdateOne(ctx, filter, update)
	return err
}

// SetMessagesBatchHidden 批量设置消息隐藏状态
func (r *MessageRepository) SetMessagesBatchHidden(chatId int64, sequenceNums []int, hidden bool) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	filter := bson.M{
		"conversation_id": chatId,
		"sequence_num": bson.M{
			"$in": sequenceNums,
		},
	}

	update := bson.M{
		"$set": bson.M{
			"hidden": hidden,
		},
	}

	_, err := core.MsgCollection.UpdateMany(ctx, filter, update)
	return err
}
